package org.zjt.chapter1.http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicLong;

/**
 * Description:
 *
 * @author juntao.zhang
 * Date: 2018-07-18 下午2:25
 * @see
 */
@Slf4j
public class HttpHelloWorldServer extends AbstractHttpServer{


    @Test
    public void main() {
        start(8080);
    }

    @Override
    public ChannelInitializer<NioSocketChannel> getChannelInitializer() {
        return new MyChannelInitializer();
    }


    public static class MyChannelInitializer extends ChannelInitializer<NioSocketChannel>{

        @Override
        protected void initChannel(NioSocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();

            // http 编解码
            pipeline.addLast(new HttpServerCodec());

            // 异常处理
            pipeline.addLast(new HttpServerExpectContinueHandler());


            // 请求处理
            pipeline.addLast(new MyRequestHandler());
        }
    }


    @Slf4j
    public static class MyRequestHandler extends ChannelInboundHandlerAdapter{
        private final AtomicLong atomicLong = new AtomicLong();

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof HttpRequest){
                HttpRequest httpRequest = HttpRequest.class.cast(msg);


                boolean keepAlive = HttpUtil.isKeepAlive(httpRequest);

                DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
                response.content().writeBytes(("hello world" + atomicLong.getAndIncrement()).getBytes());

                HttpHeaders headers = response.headers();

                headers.add("Content-Type","text/plain");

                // http body 字节数
                headers.addInt("content-length",response.content().readableBytes());

                // 告知请求方可以建立长连接
                headers.add("Connection","keep-alive");
                if (keepAlive){

                    ctx.write(response);
                }else {

                    // 实处响应后，并关闭连接
                    ctx.write(response).addListener(ChannelFutureListener.CLOSE);
                }
                ctx.flush();
            }
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

            log.error("netty 处理异常:",cause);
            ctx.close();
        }
    }
}
